﻿/*******************************************************************************
 * Copyright © Chris Watson 2013                                               *
 *                                                                             *
 * This document is a part of the source code and related artefacts for Chris  *
 * Watson's Desktop Wallpaper Guard, a software application which will detect  *
 * when another process removes the wallpaper from a Windows desktop and       *
 * restore an image of the user's choice.                                      *
 *                                                                             *
 * Author:                                                                     *
 *   Chris Watson       [mailto:chris@watson.me.uk]                            *
 * Date:                                                                       *
 *   17 August 2013                                                            *
 ******************************************************************************/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Watson.BleaknessEliminator.Properties;

namespace Watson.BleaknessEliminator
{
    /// <summary>
    /// Provides core application functionality to eliminate the bleakness
    /// caused by Windows 7 removing the desktop wallpaper because the
    /// activation period has elapsed by resetting an attractive desktop
    /// wallpaper.
    /// </summary>
    internal class Eliminator
    {
        #region Private Fields

        #endregion

        #region Internal Properties

        /// <summary>
        /// Gets or sets a value indicating whether this
        /// <see cref="Eliminator"/> is enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if enabled; otherwise, <c>false</c>.
        /// </value>
        public bool Enabled
        {
            get
            {
                return Settings.Default.Enabled;
            }
            set
            {
                if (value != Settings.Default.Enabled)
                {
                    Settings.Default.Enabled = value;

                    // Persist 'Enabled' setting change.
                    //
                    Settings.Default.Save();

                    if (Settings.Default.Enabled)
                    {
                        Trace.TraceInformation("{0} Eliminator is enabled.",
                            DateTime.Now);
                    }
                    else
                    {
                        Trace.TraceInformation("{0} Eliminator is disabled.",
                            DateTime.Now);
                    }

                    OnEnabledChanged();
                }
            }
        }

        #endregion

        #region Private Static Methods

        /// <summary>
        /// Sets the system wallpaper to the configured image.
        /// </summary>
        private static void SetWallpaper()
        {
            string path = Settings.Default.WallpaperPath;

            if (String.IsNullOrWhiteSpace(path))
            {
                Trace.TraceWarning(
                    "{0} Request to set desktop wallpaper cannot be fulfilled."
                    + " The path ('WallpaperPath' setting) has not been"
                    + " configured.",
                    DateTime.Now);
            }
            else if (!File.Exists(path))
            {
                Trace.TraceWarning(
                    "{0} Request to set desktop wallpaper cannot be fulfilled."
                    + " File not found. '{1}'.",
                    DateTime.Now, path);
            }
            else
            {
                WindowsProfileSettings.SetWallpaperIfDifferent(path);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Adds an event listener to the <see cref="Settings.PropertyChanged"/>
        /// event. The Eliminator will react to settings changing, such as the
        /// wallpaper path, without requiring a restart or waiting for the next
        /// trigger event to occur.
        /// </summary>
        private void AddSettingsChangedListener()
        {
            Settings.Default.PropertyChanged += (sender, e) =>
            {
                if (e.PropertyName == "WallpaperPath")
                {
                    OnWallpaperPathSettingChanged();
                }
            };
        }

        
        /// <summary>
        /// Called when the value of the <see cref="Enabled"/> property changes.
        /// </summary>
        private void OnEnabledChanged()
        {
            // If the user enables the Eliminator after it has started, this
            // should force an immediate wallpaper set operation.
            //
            if (Enabled)
            {
                SetWallpaper();
            }
        }


        /// <summary>
        /// Called when the value of the <see cref="Settings.Wallpaper"/>
        /// setting changes.
        /// </summary>
        private void OnWallpaperPathSettingChanged()
        {
            Trace.TraceInformation(
                "{0} WallpaperPath setting value changed to '{1}'.",
                DateTime.Now, Settings.Default.WallpaperPath);
            
            // If the user changes the path to the wallpaper, this should force
            // an immediate wallpaper set operation.
            //
            SetWallpaperIfEnabled();
        }


        /// <summary>
        /// Sets the wallpaper to the configured image if this Eliminator is
        /// enabled.
        /// </summary>
        private void SetWallpaperIfEnabled()
        {
            if (Enabled)
            {
                SetWallpaper();
            }
        }

        #endregion

        #region Internal Methods

        /// <summary>
        /// Notifies the Eliminator that the system wallpaper has changed.
        /// </summary>
        internal void NotifyWallpaperChanged()
        {
            Trace.TraceInformation(
                "{0} System wallpaper changed notification received.",
                DateTime.Now);

            SetWallpaperIfEnabled();
        }

        #endregion

        #region Internal Constructors

        /// <summary>
        /// Initialises a new instance of the <see cref="Eliminator"/> class.
        /// </summary>
        internal Eliminator()
        {
            // Listen for, and react to, settings being changed.
            //
            AddSettingsChangedListener();

            // Set wallpaper on startup if enabled.
            //
            SetWallpaperIfEnabled();
        }

        #endregion
    }
}
